package io.coderyeah.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.coderyeah.basic.annotation.PreAuthorize;
import io.coderyeah.basic.util.ClassUtils;
import io.coderyeah.system.domain.Permission;
import io.coderyeah.system.mapper.PermissionMapper;
import io.coderyeah.system.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author coderyeah
 * @description 针对表【t_permission】的数据库操作Service实现
 * @createDate 2022-09-21 11:00:07
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {
    private static final String PKG_PREFIX = "io.coderyeah.";
    private static final String PKG_SUFFIX = ".controller";
    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public void scanPermission() {
        //获取 io.coderyeah 下面所有的模块目录
        String path = this.getClass().getResource("/").getPath() + "/io/coderyeah/";
        // 当前包路径下的文件对象
        File file = new File(path);
        // 过滤出当前包下所有目录的文件数组
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.isDirectory();
            }
        });

        //获取io.coderyeah.*.controller里面所有的类
        Set<Class> clazzes = new HashSet<>();
        assert files != null;
        for (File fileTmp : files) {
            System.out.println("===============权限注解解析：获取所有的包==============");
            System.out.println(fileTmp.getName());
            // 将所有类对象放进set集合
            clazzes.addAll(ClassUtils.getClasses(PKG_PREFIX + fileTmp.getName() + PKG_SUFFIX));
        }

        // 遍历类对象集合
        for (Class clazz : clazzes) {
            // 获取当前类的所有方法
            Method[] methods = clazz.getMethods();
            // 判断是否有方法存在
            if (methods == null || methods.length < 1) {
                return;
            }
            // 遍历当前类中所有的方法
            for (Method method : methods) {
                // 获取接口执行路径
                String uri = getUri(clazz, method);
                try {
                    PreAuthorize preAuthorizeAnno = method.getAnnotation(PreAuthorize.class);
                    if (preAuthorizeAnno == null) {
                        // 跳出当前循环
                        continue;
                    }
                    String name = preAuthorizeAnno.name();
                    String permissionSn = preAuthorizeAnno.sn();
                    Permission permissionTmp = permissionMapper.selectOne(new LambdaQueryWrapper<Permission>().eq(Permission::getSn, permissionSn));
                    //如果不存在就添加
                    if (permissionTmp == null) {
                        Permission permission = new Permission();
                        permission.setName(name);       //t_permission表中的权限名
                        permission.setSn(permissionSn); //t_permission表中的权限编号
                        permission.setUrl(uri);           //t_permission表中的权限路径
                        permissionMapper.insert(permission);
                    } else {
                        //如果存在就修改
                        permissionTmp.setName(name);
                        permissionTmp.setSn(permissionSn);
                        permissionTmp.setUrl(uri);
                        permissionMapper.updateById(permissionTmp);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    //获取t_permission表中的url  //@RequestMapping("/department") //@GetMapping("/{id}")
    private String getUri(Class clazz, Method method) {
        //获取类上的请求路径：/department
        String classPath = "";
        // 获取当前类的@RequestMapping注解
        Annotation annotation = clazz.getAnnotation(RequestMapping.class);
        // 判断注解是否存在
        if (annotation != null) {
            // 类型强转
            RequestMapping requestMapping = (RequestMapping) annotation;
            // 获取@RequestMapping注解的数组值
            String[] values = requestMapping.value();
            // 判断值是否为空
            if (values != null && values.length > 0) {
                // 将请求路径赋值给classPath
                classPath = values[0];
                if (!"".equals(classPath) && !classPath.startsWith("/"))
                    classPath = "/" + classPath;
            }
        }
        //以下是获取方法上的请求路径：/{id}
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        // 方法上的请求路径
        String methodPath = "";
        if (getMapping != null) {
            // 获取注解上的值
            String[] values = getMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }

        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping != null) {
            String[] values = postMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }

        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping != null) {
            String[] values = deleteMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }

        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping != null) {
            String[] values = putMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }

        }

        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping != null) {
            String[] values = patchMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }

        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        if (requestMapping != null) {
            String[] values = requestMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }
        return classPath + methodPath;  // /department/{id}
    }

    private String getPermissionSn(String value) {
        String regex = "\\[(.*?)]";
        Pattern p = Pattern.compile("(?<=\\()[^\\)]+");
        Matcher m = p.matcher(value);
        String permissionSn = null;
        if (m.find()) {
            permissionSn = m.group(0).substring(1, m.group().length() - 1);
        }
        return permissionSn;
    }

    public static void main(String[] args) {
        String regex = "\\[(.*?)]";
        String text = "hasAuthority('permission:add')";
        Pattern p = Pattern.compile("(?<=\\()[^\\)]+");
        Matcher m = p.matcher(text);
        if (m.find()) {
            System.out.println(m.group(0).substring(1, m.group().length() - 1));
        }
    }
}




